home *** CD-ROM | disk | FTP | other *** search
/ No Fragments Archive 12: Textmags & Docs / nf_archive_12.iso / MAGS / SOURCES / ATARI_SRC.ZIP / atari source / AHDI / SYQUEST / SQHDX / BSL.C < prev    next >
Encoding:
C/C++ Source or Header  |  2001-02-09  |  19.0 KB  |  671 lines

  1. /*
  2.  * BSL.C
  3.  *
  4.  *     Functions to manipulate the Bad Sector List.
  5.  *
  6.  * 25-Nov-87    ml.    Started this mess.
  7.  * 04-Dec-87    ml.    Hmmm, looks OK.
  8.  * 11-Dec-87    ml.    Added bsl2fat().
  9.  * 14-Dec-87    ml.    Structure of BSL is changed (_again_!).
  10.  *            Now, first entry in BSL contains number VENDOR
  11.  *            entries.  First byte of 2nd entry is the checksum
  12.  *            byte, while 2nd and 3rd bytes are reserved for 
  13.  *            future use.
  14.  *
  15.  */
  16.  
  17. #include "obdefs.h"
  18. #include "osbind.h"
  19. #include "defs.h"
  20. #include "part.h"
  21. #include "bsl.h" 
  22. #include "hdx.h"
  23. #include "addr.h" 
  24. #include "error.h" 
  25.  
  26. /* Globals */
  27. BYTE *bsl;            /* bad sector list */
  28. long bslsiz;            /* num sectors BSL occupies */
  29. SECTOR badbuf[WARNBADSECTS];    /* bad sectors buffer */
  30. extern int format;        /* 1: called by Format */
  31.  
  32.  
  33. /*
  34.  *  Get size of the Bad Sector List (in sectors)
  35.  *    Input:
  36.  *        pdev - physical unit BSL belongs to.
  37.  *    Return:
  38.  *        number of sectors BSL occupies.
  39.  */
  40. long 
  41. gbslsiz(pdev) 
  42. int pdev;    /* physical device number */
  43. {
  44.     char bs[512];    /* boot sector image */
  45.     UWORD  ret;
  46.     
  47.     if ((ret = getroot(pdev, bs)) != 0) {
  48.         if (tsterr(ret) == OK)
  49.         return MDMERR;
  50.     else return ERROR;
  51.     }
  52.     
  53.     if (((RSECT *)(bs + 0x200 - sizeof(RSECT)))->bsl_st != STBSL)
  54.         return 0L;
  55.         
  56.     return(((RSECT *)(bs + 0x200 - sizeof(RSECT)))->bsl_cnt);
  57. }
  58.  
  59.  
  60. /*
  61.  *  Set BSL parameters (starting sector and size of BSL) into
  62.  *  root sector image.
  63.  *    Input:
  64.  *        image - root sector image.
  65.  */
  66. sbslparm(image)
  67. char *image;
  68. {
  69.     ((RSECT *)(image + 0x200 - sizeof(RSECT)))->bsl_st = STBSL;
  70.     ((RSECT *)(image + 0x200 - sizeof(RSECT)))->bsl_cnt = bslsiz;
  71. }
  72.  
  73.  
  74. /* 
  75.  *  Create a BSL in memory.
  76.  *    Input:
  77.  *        pdev - physical unit BSL will belong to.
  78.  *        type - kind of BSL to be created. NEW or EXPAND.
  79.  *        nents - number of VENDOR entries BSL should hold.
  80.  *    Output:
  81.  *        bsl - pointer to the BSL. (in bsl.h)
  82.  *    Return:
  83.  *        OK - everything is fine.
  84.  *        ERROR - anything is wrong.
  85.  *    Comment:
  86.  *        "NEW" means to create a totally new BSL.
  87.  *        "EXPAND" means to expand an existing BSL.
  88.  */
  89. creabsl(pdev, type, nents)
  90. int  pdev;    /* physical unit number */
  91. int  type;    /* kind of BSL to be created */
  92. long  nents;    /* num VENDOR entries in BSL */
  93. {
  94.     BYTE *newbsl;  /* BSL just created */
  95.     long l, size;  /* l - index into BSL;  size - size of BSL in bytes */ 
  96.     long start;       /* where to start initializing entries to zeroes */
  97.     long nument();
  98.  
  99.     if (nents == 0) {    /* no VENDOR entries specified */
  100.         size = 512L;    /* default size of BSL to 1 sector */
  101.     } else {       /* num VENDOR entries is specified */
  102.         /*------------------------------------------------------*/
  103.         /* Calculate length of BSL in bytes.            */
  104.         /* Have to add space for reserved entries and USER list    */
  105.         /* (note: (+1) to round up)                */
  106.         /*------------------------------------------------------*/
  107.     size = (((nents + RENT + WARNBADSECTS)/EPS) + 1) * 512L;
  108.     }
  109.     
  110.     /* allocate enough memory for new BSL */
  111.     if ((newbsl = (BYTE *)mymalloc((int)size)) <= 0)
  112.         return err(nomemory);
  113.     
  114.     if (type == NEW) {    /* a new BSL */
  115.         start = 0;    /* start at 0th entry, i.e. init whole BSL to 0s */
  116.     }    
  117.     else {        /* expand the BSL */
  118.         /* start init to 0s after VENDOR list */
  119.     start = (nument(VENDOR) + RENT) * BPE;
  120.     
  121.         /* copy original BSL into this expanded memory */
  122.         for (l = 0; l < start; l++)
  123.             newbsl[l] = bsl[l];
  124.     }
  125.         
  126.             
  127.     /* free up old BSL */
  128.     if (bsl > 0) free(bsl);
  129.     bsl = newbsl;
  130.     
  131.     /* init BSL to zeroes beginning at 'start'th entry */
  132.     for (l = start; l < size; l++)
  133.         bsl[l] = 0;
  134.         
  135.     /* install BSL info */
  136.     bslsiz = size/512;    /* current num sectors BSL occupies */
  137.     put3bytes(bsl, nents);  /* num VENDOR entries */
  138.     mkmagic();    /* make the BSL checks sum to BSLMAGIC byte-wise */
  139.                           
  140.     return OK;
  141. }
  142.  
  143.  
  144. /*
  145.  *  Read the BSL into memory.
  146.  *    Input:
  147.  *        pdev - physical unit that contains the BSL.
  148.  *    Output:
  149.  *        bsl - pointer to the BSL.  (in bsl.h)
  150.  *    Return:
  151.  *        OK - everything is fine.
  152.  *        INVALID - BSL doesn't checksum correctly.
  153.  *        ERROR - can't read BSL.
  154.  */
  155. rdbsl(pdev)
  156. int pdev;    /* physical unit to read from */
  157. {
  158.     int ret;
  159.     
  160.     if ((ret = rdsects(pdev, (UWORD)bslsiz, bsl, (SECTOR)STBSL)) != 0) {
  161.         if (tsterr(ret) != OK) {
  162.             if (format == FALSE)
  163.             err(bslread);
  164.     }
  165.     return ERROR;
  166.     }
  167.         
  168.     return(sumbsl());    /* Checksum BSL and return */
  169. }
  170.  
  171.  
  172. /*
  173.  *  Count number of entries in the requested portion of BSL.
  174.  *    Input:
  175.  *        portion - portion of BSL.  MEDIA, VENDOR, USER or UNUSED.
  176.  *    Return:
  177.  *        Number of entries of the requested portion.
  178.  *    Comments:
  179.  *        There are 3 bytes per entry (BPE), and the first 2 entries
  180.  *    are reserved (RENT) for BSL info.
  181.  */
  182. long
  183. nument(portion)
  184. int portion;        /* portion of BSL to be counted */
  185. {
  186.     long  vdr, usr;        /* num ent in VENDOR list, num ent in USER list */
  187.     long  nbytes, offset;   /* BSL's len in bytes, index into BSL */
  188.     long  get3bytes();
  189.     
  190.     /* 1st entry in BSL contains num entries in VENDOR list */
  191.     vdr = get3bytes(bsl);
  192.     
  193.     if (portion == VENDOR)  return (vdr);
  194.     
  195.     nbytes = bslsiz*512;    /* num bytes in BSL */
  196.     
  197.     /* num bytes available for valid entries */
  198.     /* (need this because nbytes may not be divisible by BPE) */
  199.     nbytes -= (nbytes % BPE);
  200.     
  201.     /* find out num entries in USER list */
  202.     usr = 0;
  203.     for (offset = (RENT+vdr)*BPE;  /* index into beginning of USER list */
  204.          (offset < nbytes)       /* while not at end of BSL */
  205.      && get3bytes(bsl+offset); /* and it's a used entry */
  206.          offset += BPE)           /* increment index */
  207.         usr++;        /* increment num entries for USER list */
  208.          
  209.     if (portion == USER)
  210.         return (usr);        /* num entries in USER list */
  211.         
  212.     if (portion == MEDIA)
  213.         return (vdr+usr);    /* num entries in MEDIA list */     
  214.         
  215.     /* portion == UNUSED */
  216.     return ((nbytes/BPE)-RENT-vdr-usr);
  217. }
  218.  
  219.  
  220. /*
  221.  *  Write the BSL into the disk.
  222.  *    Input:
  223.  *        pdev - physical unit number BSL belongs to.
  224.  *        bsl - pointer to buffer containing the BSL. (in bsl.h)
  225.  *    Return:
  226.  *        OK - everything is fine.
  227.  *        ERROR - can't write BSL.
  228.  */
  229. wrbsl(pdev)
  230. int pdev;    /* physical unit number */
  231. {
  232.     int ret;            /* return code */
  233.     
  234.     if ((ret = wrsects(pdev, (UWORD)bslsiz, bsl, (SECTOR)STBSL)) != 0) {
  235.         if (tsterr(ret) != OK)
  236.             err(bslwrite);
  237.         return ERROR;
  238.     }
  239.  
  240.     return OK;
  241.  
  242.  
  243. /*
  244.  *  Sort the BSL in memory in ascending order.
  245.  *    Input:
  246.  *        entries - number of used entries in BSL
  247.  *        bsl - pointer to the BSL. (in bsl.h)
  248.  *    Output:
  249.  *        a sorted bsl.
  250.  *    Algorithm:
  251.  *        Bubble sort.
  252.  *    Comments:
  253.  *        The reserved entries won't be sorted.
  254.  */
  255. sortbsl(entries)
  256. long  entries;    /* num entries in BSL */
  257. {
  258.     long  i, e1, e2;
  259.     long  start;    /* beginning byte of entries in BSL */
  260.     long  end;        /* tail byte of BSL */
  261.     int   change;    /* signal if changes have been made in current pass */
  262.     long  get3bytes();
  263.     
  264.     if (entries == 0L || entries == 1L)    /* BSL is empty */
  265.         return;
  266.             
  267.     change = 1;        /* assume list is not in order */
  268.     start = RENT*BPE;    /* beginning of entries in BSL */
  269.     end = entries * BPE;
  270.     while (1) {
  271.         if (change == 0)    /* if no changes made, DONE --> HOME */
  272.         return;
  273.         
  274.         change = 0;    /* assume list is in order */
  275.         for (i = start; i <= end; i += BPE) {
  276.             e1 = get3bytes(bsl+i);
  277.             e2 = get3bytes(bsl+i+BPE);
  278.             if (e1 > e2) {            /* switch if out of order */
  279.                 put3bytes(bsl+i, e2);
  280.                 put3bytes(bsl+i+BPE, e1);
  281.                 change = 1;
  282.             }
  283.         }
  284.         end -= BPE;
  285.     }
  286. }
  287.  
  288.  
  289. /*
  290.  *  Search through a sorted BSL for a given sector number.
  291.  *    Input:
  292.  *        sect - sector number searching for.
  293.  *        entries - number of used entries in the BSL.
  294.  *    Return:
  295.  *        YES - if given sector is found.
  296.  *        NO - if given sector is not found.
  297.  *    Algorithm:
  298.  *        Binary Search.
  299.  */
  300. srchbsl(sect, entries)
  301. SECTOR  sect;    /* sector searching for */
  302. long  entries;    /* num used entries in BSL */
  303. {
  304.     long  start, mid, end; /* start, middle and end indices into list */
  305.     SECTOR  temp;       /* sector number in middle of list */
  306.     long  get3bytes();
  307.  
  308.     start = RENT;        /* start after reserved entries */
  309.     end = entries+RENT-1;    /* end of BSL */ 
  310.     
  311.     while (1) {
  312.          mid = (start + end) / 2;        /* middle entry in list */
  313.         temp = get3bytes(bsl+(mid*BPE));    /* sector num at mid entry */
  314.         
  315.         if (sect == temp)    /* given sector == sector at mid entry */
  316.             return YES;        /* given sector found in list */
  317.         else if (sect < temp)    /* given sector < sector at mid entry */
  318.             end = mid - 1;    /* limit search to smaller sector num */
  319.         else            /* given sector > sector at mid entry */
  320.             start = mid + 1;    /* limit search to larger sector num */
  321.             
  322.         if (end < start)    /* list is exhausted */
  323.             return NO;        /* can't find given sector */    
  324.     }
  325. }
  326.  
  327.  
  328. /*
  329.  *  Checksum (byte-wise) the BSL.
  330.  *    Input:
  331.  *        bsl - pointer to the BSL.  (in bsl.h)
  332.  *    Return:
  333.  *        OK - BSL checksum to BSLMAGIC (0xa5).
  334.  *        INVALID - BSL does not checksum to BSLMAGIC.
  335.  */
  336. sumbsl()
  337. {
  338.     register BYTE sum;    /* byte-wise sum of BSL */
  339.     long i;        /* index into BSL */
  340.     long length;    /* length of BSL in bytes */
  341.  
  342.     length = bslsiz*512;    /* length of entire BSL */
  343.     sum = 0;    /* initialize the sum */
  344.     
  345.     /* Sum up values in the BSL by byte */
  346.     for (i = 0; i < length; i++) {
  347.         sum += bsl[i];
  348.     }
  349.     if (sum != BSLMAGIC) {    /* doesn't checksum correctly */
  350.         return INVALID;
  351.     }
  352.     return OK;    /* checksum correctly */
  353. }
  354.  
  355.  
  356. /*
  357.  *  Make the BSL checks sum to BSLMAGIC.
  358.  */
  359. mkmagic()
  360. {
  361.     register BYTE diff;    /* difference to make BSL checks sum correctly */
  362.     long i;        /* index into BSL */
  363.     long len;        /* length of BSL in bytes */
  364.     
  365.     len = bslsiz*512;    /* length of entire BSl */
  366.     diff = BSLMAGIC;    /* initialize the difference */
  367.     
  368.     /* find out what number would make BSL checks sum to BSLMAGIC */
  369.     for (i = 0; i < len; i++) {
  370.         diff -= bsl[i];
  371.     }
  372.     
  373.     /* add that difference to checksum byte (1st byte of 2nd entry of BSL) */
  374.     bsl[BPE] += diff;
  375. }
  376.  
  377.  
  378. /*
  379.  *  Add bad sectors found to the Bad Sector List.
  380.  *    Input:
  381.  *        pdev - physical unit BSL belongs to.
  382.  *        portion - portion of BSL to add to.  VENDOR or USER.
  383.  *        nbad - number of bad sectors to be added.
  384.  *    Return:
  385.  *        toadd - number of new bad sectors added to the BSL.
  386.  *        USRFULL - user part of the BSL is filled up.
  387.  *        NOMEM - not enough memory for add buffer or BSL.
  388.  *        ERROR - something is wrong.
  389.  *    Comment:
  390.  *        The entry will be added only if it is not already on the
  391.  *    bad sector list.  Binary search is performed to guarantee this.
  392.  *        If the VENDOR list is full, this routine will take care
  393.  *    of the expansion of the list also.
  394.  */
  395. addbsl(pdev, portion, nbad) 
  396. int pdev;        /* physical unit number */
  397. int portion;        /* portion of BSL */
  398. int nbad;        /* num of bad sectors to be added */
  399. {
  400.     long  entries;    /* num entries to be retained in BSL */
  401.     long  empty;    /* num empty slots available for adding entries */
  402.     long  end;        /* address of end of BSL */
  403.     int  i, toadd;    /* index to badbuf, num of bad sectors to be added */
  404.     int  ret = 0;    /* return code */
  405.     SECTOR *addbuf;    /* bad sectors to be added to BSL */
  406.     long  nument();
  407.     
  408.     /* Allocate memory for sector numbers of bad sectors to be added */
  409.     if ((addbuf = (SECTOR *)mymalloc(nbad*4)) <= 0) {
  410.         err(nomemory);
  411.         return NOMEM;
  412.     }
  413.     
  414.     if (portion == VENDOR) {    /* adding to VENDOR list */
  415.         entries = nument(VENDOR);   /* only keep the VENDOR list */
  416.         empty = 0;            /* there's no unused slot for VENDOR ent */
  417.     } else {            /* adding to USER list */
  418.         entries = nument(MEDIA);    /* keep entire list */
  419.         empty = nument(UNUSED);     /* slots left unused */
  420.     }
  421.     sortbsl(entries);        /* sort BSL in ascending order */
  422.     toadd = 0;            /* none is to be added to BSL yet */
  423.  
  424.     /* For all bad sectors found, search for them in the current BSL.
  425.        Add them to the list only when they are not already recorded.  */    
  426.     if (entries) {    /* only search if BSL is not empty */
  427.     for (i = 0; i < nbad; i++) {
  428.         if (srchbsl(badbuf[i], entries) == NO) {
  429.         addbuf[toadd] = badbuf[i];
  430.         toadd++;
  431.         }
  432.         }
  433.     } else {  /* add in all bad sectors found */
  434.     for (i = 0; i < nbad; i++)
  435.         addbuf[i] = badbuf[i];
  436.         toadd = nbad;
  437.     }
  438.     
  439.     /* All bad sectors found have been recorded.  Nothing is added to BSL */
  440.     if (toadd == 0) {
  441.         if (portion == USER && (ret = rdbsl(pdev)) != OK) {
  442.             if (ret == INVALID)
  443.                 err(cruptbsl);
  444.         goto togo;
  445.     }
  446.         ret = toadd;
  447.     }
  448.     
  449.     /*------------------------------------------------------------------*/
  450.     /* Check if there are enough empty slots for new entries.  If not,    */
  451.     /* determine what kind of entries we are adding, VENDOR or USER.    */    
  452.     /* Expand the BSL if we are adding to VENDOR list.  Give warning    */
  453.     /* if we are adding to USER list.                          */
  454.     /*------------------------------------------------------------------*/
  455.     if (toadd > empty) {
  456.         if (portion == VENDOR) {    /* this only happens at format time */
  457.         /* expanded BSL should hold (entries + toadd) VENDOR entries */
  458.         if (creabsl(pdev, EXPAND, entries+toadd) != OK)
  459.             goto togo;
  460.         } else {            /* We are adding to USER list */
  461.             err(manybad);
  462.             toadd = empty;    /* num ent to add = empty slots available */
  463.         }
  464.     }
  465.     
  466.     /* Read in orig unsorted list if adding USER entries */
  467.     if (portion == USER) {
  468.         if ((ret = rdbsl(pdev)) != OK) {
  469.             if (ret == INVALID)
  470.                 err(cruptbsl);
  471.             goto togo;
  472.         }
  473.     }
  474.                 
  475.     /* Append new entries to end of BSL */
  476.     end = bsl + (RENT + entries)*BPE;    /* end of BSL */
  477.     for (i = 0; i < toadd; i++) {
  478.         put3bytes((end + i*BPE), addbuf[i]);
  479.     }
  480.     
  481.     /* make BSL checks sum to magic number */
  482.     mkmagic();
  483.  
  484.     if (portion == USER && toadd == empty) {
  485.         ret = USRFULL;
  486.         goto togo;
  487.     }
  488.         
  489.     ret = toadd;
  490.     
  491. togo:
  492.     if (addbuf > 0) free(addbuf);            
  493.     return(ret);
  494. }
  495.  
  496.  
  497. /*
  498.  *  Mark bad sectors from the BSL to FATs of a partition.
  499.  *    Input:
  500.  *        ldev - logical device the FATs belong to.
  501.  *        fat0 - logical sector number of where FAT 0 starts.
  502.  *        fatsiz - size of FAT in sectors.
  503.  *        data - logical sector number of where data clusters start.
  504.  *        portion - part of BSL to mark from.
  505.  */
  506. bsl2fat(ldev, fat0, fatsiz, data, portion)
  507. int  ldev;    /* logical device number */
  508. SECTOR fat0;    /* starting sector number (logical) of FAT 0 */ 
  509. UWORD fatsiz;    /* FAT size */
  510. SECTOR data;    /* starting sector number (logical) of data clusters */
  511. int portion;    /* part of BSL to mark from, VENDOR or MEDIA */
  512. {
  513.     long nument(), entries;    /* num entries in the list to be considered */
  514.     long i, end;        /* indices to the list to be considered */
  515.     SECTOR badsect;        /* a bad sector in the list */
  516.     SECTOR pstart;        /* phys sector num where partition starts */
  517.     SECTOR pdata;        /* phys sector num where data block starts */
  518.     SECTOR pend;        /* phys sector num where data block ends */
  519.     SECTOR logstart(), logend();
  520.     int nbad;
  521.     
  522.     nbad = 0;            /* assume none to be marked */
  523.     pstart = logstart(ldev);    /* find where partition starts */
  524.     pdata = pstart + data;    /* find where data block starts */
  525.     pend = logend(ldev);    /* find where data block ends */    
  526.     entries = nument(portion);    /* find num entries in given portion */
  527.     sortbsl(entries);        /* sort given portion of BSL */
  528.     
  529.     end = (RENT + entries) * BPE;
  530.     
  531.     /* Store vendor bad sectors of the logical device in badbuf */
  532.     for (i = BPE*RENT; i < end; i += BPE) {
  533.         if ((badsect = get3bytes(bsl+i)) > pend)
  534.             break;
  535.             
  536.         if (badsect >= pdata) {
  537.             badbuf[nbad++] = badsect;
  538.             
  539.             /* if badbuf overflows, mark what we have so far in the FAT */
  540.             if (nbad == WARNBADSECTS) {
  541.                 if (fixbadcls(ldev, fat0, fatsiz, data, nbad) < 0) {
  542.                     return ERROR;
  543.                 }
  544.                 nbad = 0;    /* reinit num bad sectors in partition to 0 */
  545.             }
  546.         }
  547.     }
  548.     
  549.     /* Bad sectors in partition not marked in FAT yet */
  550.     if (nbad) {
  551.         if (fixbadcls(ldev, fat0, fatsiz, data, nbad) < 0) {
  552.             return ERROR;
  553.         }
  554.     }
  555.     
  556.     return OK;
  557. }
  558.  
  559.  
  560. /*
  561.  *  Count number of bad sectors on a logical drive recorded in BSL.
  562.  *    Input:
  563.  *        ldev - logical drive to be considered.
  564.  *    Return:
  565.  *        nbad - number of bad sectors found.
  566.  */
  567. long
  568. cntbad(ldev)
  569. int  ldev;    /* logical drive number */
  570. {
  571.     SECTOR pstart, pend;    /* phys starting and ending block of ldev */
  572.     extern SECTOR logstart(), logend();
  573.     long nbad=0L;        /* num bad sectors on ldev */
  574.     long entries, nument(), bslend;
  575.     long curr, get3bytes();
  576.     int done, i;
  577.     
  578.     pstart = logstart(ldev);    /* starting block # of partition */
  579.     pend = logend(ldev);    /* ending block # of partition */
  580.     entries = nument(MEDIA);    /* num entries in BSL */
  581.     sortbsl(entries);        /* sort BSL */
  582.     
  583.     done = 0;
  584.     bslend = (RENT+entries) * BPE;
  585.     for (i = RENT*BPE; (!done) && (i < bslend); i += BPE) {
  586.         curr = get3bytes(bsl+i);  /* get next entry in BSL */
  587.         if (curr < pstart)      /* not within logical drive's range yet */
  588.             continue;
  589.         if (curr <= pend)      /* within logical drive's range */
  590.             nbad++;
  591.         else done = 1;          /* pass logical drive's range */
  592.     }
  593.     return (nbad);
  594. }
  595.  
  596.  
  597. /*
  598.  *  Put a word into memory in 68000 format.
  599.  *    Input:
  600.  *        p - pointer to memory.
  601.  *        i - word to be put.
  602.  */
  603. putword(p, i)
  604. BYTE *p;
  605. UWORD i;
  606. {
  607.     *p = i >> 8;
  608.     *(p+1) = i;
  609. }
  610.  
  611.  
  612. /*
  613.  *  Get a 68000 format word from memory.
  614.  *    Input:
  615.  *        p - pointer to memory.
  616.  *    Return:
  617.  *        i - word read from memory.
  618.  */        
  619. getword(p)
  620. BYTE *p;
  621. {
  622.     UWORD i;
  623.     
  624.     i = *p;
  625.     i <<= 8;
  626.     i |= *(p+1);
  627.     return (i);
  628. }
  629.  
  630.  
  631. /*
  632.  *  Put 3 bytes (68000 format) into memory.
  633.  *    Input:
  634.  *        p - pointer to memory.
  635.  *        l - long which contains the 3 bytes at the low-bit end.
  636.  */
  637. put3bytes(p, l)
  638. BYTE *p;
  639. long l;
  640. {
  641.     *p = l >> 16;
  642.     *(p+1) = l >> 8;
  643.     *(p+2) = l;
  644. }    
  645.  
  646.  
  647. /*
  648.  *  Get 3 bytes (68000 format) from memory.
  649.  *    Input:
  650.  *        p - pointer to memory.
  651.  *    Return:
  652.  *        l - a long which contains the 3 bytes read in last 3 bytes.
  653.  */
  654. long
  655. get3bytes(p)
  656. BYTE *p;
  657. {
  658.     long  k=0x000000ff, l=0x000000ff;
  659.     
  660.     l &= *p;        /* first byte */
  661.     l <<= 16;
  662.     k &= *(p+1);    /* second byte */
  663.     k <<= 8;
  664.     l |= k;
  665.     k = 0x000000ff;
  666.     k &= *(p+2);    /* third byte */
  667.     l |= k;
  668.     return (l);
  669. }
  670.